package com.projectx.action.draw;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Xfermode;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;


public class DrawBoardView extends View {
    private final int MAX_PAINT_RECORD = 20;
    private int mWidth;
    private int mHeight;
    private float preX;
    private float preY;
    private Path mPath;
    private Paint mPaint;//用传入的画笔作画
    private DrawPath drawPath;
    private List<DrawPath> mPaintedPath = new ArrayList<>();
    private List<DrawPath> mRevokedPath = new ArrayList<>();
    private Canvas cacheCanvas;
    private Bitmap cacheBitmap;
    private Canvas mHoldCanvas;//固化超过撤销最大数量的笔迹
    private Bitmap mHoldBitmap;//固化位图
    private Context context;
    private boolean isMoved = false;

    public DrawBoardView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        mPath = new Path();
        mPaint = initPaint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mPaintedPath.size() > MAX_PAINT_RECORD){
            DrawPath pathData = mPaintedPath.remove(0);
            mHoldCanvas.drawPath(pathData.getPath(),pathData.getPaint());
        }
        cacheCanvas.drawBitmap(mHoldBitmap,0,0,null);
        for (DrawPath p:mPaintedPath
             ) {
            cacheCanvas.drawPath(p.getPath(),p.getPaint());
        }
        canvas.drawBitmap(cacheBitmap,0,0,null);
    }



    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        if (cacheCanvas == null){//测绘屏幕宽度后设置画布
            cacheBitmap = Bitmap.createBitmap(mWidth,mHeight, Bitmap.Config.ARGB_8888);
            cacheCanvas = new Canvas(cacheBitmap);
        }
        if (mHoldCanvas == null){
            mHoldBitmap = Bitmap.createBitmap(mWidth,mHeight, Bitmap.Config.ARGB_8888);
            mHoldCanvas = new Canvas(mHoldBitmap);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                Path path = new Path();
                path.moveTo(event.getX(),event.getY());
                isMoved = false;
                preX = event.getX();
                preY = event.getY();
                drawPath = new DrawPath();
                drawPath.setPaint(mPaint);
                drawPath.setPath(path);
                mPaintedPath.add(drawPath);
                break;
            case MotionEvent.ACTION_MOVE:
                drawPath.getPath().quadTo(preX,preY,event.getX(),event.getY());
                invalidate();
                preX = event.getX();
                preY = event.getY();
                isMoved = true;
                break;
            case MotionEvent.ACTION_UP:
                if (!isMoved && mPaintedPath.size() != 0){ //滤除只是按下没有移动的操作
                    mPaintedPath.remove(mPaintedPath.size() - 1);
                } else {
                    mRevokedPath.clear();
                }
                mPath.reset();
        }
        invalidate();
        return true;
    }



    public void setEditMode(EditMode mode){
        mPaint = initPaint(mPaint);
        switch (mode){
            case EDIT_MODE_PAN:
                mPaint.setXfermode(null);
                break;
            case EDIT_MODE_ERASER:
                mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        }
    }

    public void clear(){
        mHoldCanvas.drawColor(0,PorterDuff.Mode.CLEAR);
        cacheCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        mPaintedPath.clear();
        mRevokedPath.clear();
        mPaint.setXfermode(null);
        invalidate();
    }

    public boolean undo(){
        int last = mPaintedPath.size() - 1;
        if (last < 0){
            return false;
        }
        mRevokedPath.add(mPaintedPath.remove(last));
        reDraw(mPaintedPath);
        return true;
    }

    public boolean redo(){
        int last = mRevokedPath.size() - 1;
        if (last < 0){
            return false;
        }
        mPaintedPath.add(mRevokedPath.remove(last));
        reDraw(mPaintedPath);
        return true;
    }

    private void reDraw(List<DrawPath> pathList){
        cacheCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        invalidate();
    }

    public Paint getPaint() {
        return mPaint;
    }

    public Paint initPaint(){
        Paint paint;
        paint = new Paint(Paint.DITHER_FLAG);
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.STROKE);//设置填充方式为描边
        paint.setStrokeJoin(Paint.Join.ROUND);//设置笔刷转弯处的连接风格
        paint.setStrokeCap(Paint.Cap.ROUND);//设置笔刷的图形样式(体现在线的端点上)
        paint.setStrokeWidth(9);//设置默认笔触的宽度为9像素
        paint.setAntiAlias(true);//设置抗锯齿效果
        paint.setDither(true);//使用抖动效果
        return paint;
    }

    private Paint initPaint(Paint paint){
        Paint paint1 = initPaint();
        paint1.setStrokeWidth(paint.getStrokeWidth());
        paint1.setColor(paint.getColor());
        paint1.setXfermode(paint.getXfermode());
        return paint1;
    }

    public void setPaint(Paint paint){
        mPaint = initPaint(paint);
    }

    public boolean save(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.CHINA);
        final String format = sdf.format(new Date());
        final Bitmap bitmap = Bitmap.createBitmap(mWidth,mHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(Color.WHITE);
        canvas.drawBitmap(mHoldBitmap,0,0,null);
        canvas.drawBitmap(cacheBitmap,0,0,null);
        final FileOutputStream fileOS;
        try {
            final File file = new File(Environment
                    .getExternalStorageDirectory().toString()
                    + "/ProjectX/"
                    + format
                    + ".png");
            fileOS = new FileOutputStream(file);
            FutureTask<Boolean> futureTask = new FutureTask<Boolean>(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    bitmap.compress(Bitmap.CompressFormat.PNG,100,fileOS);
                    bitmap.recycle();
                    fileOS.flush();
                    fileOS.close();

                    context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));

                    return true;
                }
            });
            new Thread(futureTask).start();
            try {
                return futureTask.get();
            } catch (Exception e){
                Log.d("public", "save: 压缩bitmap出错");
            }

        } catch (IOException e){
            e.printStackTrace();
            Log.d("public", "save: io错误");
            return false;
        }
        return true;
    }
}
